package sk.fei.vrml.objects;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.FloatBuffer;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.glu.GLUquadric;

import sk.fei.vrml.main.Constants;
import sk.fei.vrml.main.FieldException;

import com.sun.opengl.util.texture.TextureData;
import com.sun.opengl.util.texture.TextureIO;

/**
 * VrmlAppearance class represents appearance node inside shape node
 * 
 * http://www.lighthouse3d.com/vrml/tutorial/index.shtml?appea
 * 
 * Appearance {
 *    	material NULL 
 *   	texture NULL 
 *  	textureTransform NULL 
 * } 
 * 
 * Material attribute is VRML Material node
 * 
	    diffuseColor 0.8 0.8 0.8 
	    ambientIntensity 0.2 
	    emissiveColor 0.0 0.0 0.0 
	    specularColor 0.0 0.0 0.0 
	    shininess 0.2 
	    transparency 0.0 
 * 
 * Texture attribute is one of ImageTexture, MovieTexture, or PixelTexture.
 * 
 * TextureTransform specifies how texture is applied to the geometry.
 * 
	    scale 1 1 
	    rotation 0 
	    center 0 0 
	    translation 0 0 
 * 
 * @author anubis
 * 
 */
public class VrmlAppearance extends VrmlObject {
	
	private MaterialObject material;
	private TextureObject texture;
	private TextureTransformObject textureTransform;
	
	public VrmlAppearance(){
		this.type = Constants.Appearance;
		// Defaultne hodnoty pri vytvarani objektu
		float defDiffuseColor[] = {  0.1f, 0.5f, 0.8f, 1.0f };
		float defAmbientIntensity = (float)1.0;
		float defEmissiveColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
		float defSpecularColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
		float defShininess = (float) 4.0;
		float defTransparency = (float) 0.0;
		   
		material = new MaterialObject(defDiffuseColor,defAmbientIntensity,defEmissiveColor,defSpecularColor,defShininess,defTransparency);
		/*try {
			File file=new File("D:\\Eclipse Workspaces\\Vrml_Editor\\church2.png");
			setImageTexture(file.toURL(),true,true);
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}*/
	}
	
	public MaterialObject getMaterial() {
		return material;
	}
	
	public TextureObject getTexture() {
		return texture;
	}
	
	public TextureTransformObject getTextureTransform() {
		return textureTransform;
	}
	
	public void applyObjectMaterial(GLAutoDrawable GLAutoDrawable){
		//if (this.texture != null) return;
		if (material == null)return;	
		GL gl = GLAutoDrawable.getGL();
		gl.glDisable(GL.GL_TEXTURE_2D);
		gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE,  FloatBuffer.wrap(material.diffuseColor));
		//gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT, material.diffuseColor);
		gl.glMaterialf(GL.GL_FRONT, GL.GL_AMBIENT,  material.ambientIntensity);
		gl.glMaterialfv(GL.GL_FRONT, GL.GL_EMISSION,  FloatBuffer.wrap(material.emissiveColor));
		gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR,  FloatBuffer.wrap(material.specularColor));
		gl.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, material.shininess);
	}
	
	public void setImageTexture(ImageTextureObject imageObject){
		TextureData textureData ;
		try {
			if (imageObject.getTextureUrl().getPath().endsWith("png")) textureData = TextureIO.newTextureData(imageObject.getTextureUrl(), false, "png");
			else if (imageObject.getTextureUrl().getPath().endsWith("jpg")) textureData = TextureIO.newTextureData(imageObject.getTextureUrl(), false, "jpg");
			else if (imageObject.getTextureUrl().getPath().endsWith("gif")) textureData = TextureIO.newTextureData(imageObject.getTextureUrl(), false, "gif");
			else throw new Exception("Texture image format not supported.");
         }
         catch (Exception exc) {
             exc.printStackTrace();
             return;
         } 
		this.texture = new ImageTextureObject(imageObject.getTextureUrl(),imageObject.isRepeatS(),imageObject.isRepeatT(),textureData);
	}
	
	public void setPixelTexture(int width, int height, int depth, boolean s, boolean t, byte[] pixel) throws Exception{
		if (width*height*depth != pixel.length){
			throw new FieldException("Not enough values inserted. Expecting "+ width*height*depth + " values.");
		}
		if (depth>4 && depth<1) return;	
		this.texture = new PixelTextureObject(width,height,depth,s,t,pixel);
	}
	
	
	public void applyTexture(GLAutoDrawable GLAutoDrawable,GLUquadric quadratic){
			if (this.texture == null)return;		
			else if (this.texture.textureType == Constants.ImageTexture){
				ImageTextureObject textureObject = (ImageTextureObject)this.texture;
				GL gl = GLAutoDrawable.getGL();
				textureObject.convertTextureDataToTexture(gl);
				textureObject.bindTexture(gl);
				gl.glBindTexture(GL.GL_TEXTURE_2D, textureObject.getTextureId());
				gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);
				gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
				gl.glTexParameteri (GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
				gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR); 
			    gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR); 
				GLU glu = new GLU();
				glu.gluQuadricTexture(quadratic, true);
			}else if (this.texture.textureType == Constants.PixelTexture){
				PixelTextureObject textureObject = (PixelTextureObject)this.texture;
				GL gl = GLAutoDrawable.getGL();
				textureObject.prepareTexture(gl);
				textureObject.bindTexture(gl);
				gl.glBindTexture(GL.GL_TEXTURE_2D, textureObject.getTextureId());
				gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
				gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
				gl.glTexParameteri (GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
				gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR); 
			    gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR); 
				GLU glu = new GLU();
				glu.gluQuadricTexture(quadratic, true);
			}
			
	}
	
	public void applyCubeTexture(GLAutoDrawable GLAutoDrawable){
		if (this.texture == null)return;		
		else if (this.texture.textureType == Constants.ImageTexture){
			ImageTextureObject textureObject = (ImageTextureObject)this.texture;
			GL gl = GLAutoDrawable.getGL();
			textureObject.convertTextureDataToTexture(gl);
			textureObject.bindTexture(gl);
			//gl.glBindTexture(GL.GL_TEXTURE_2D, textureObject.getTextureId());
			gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
			gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
			gl.glTexParameteri (GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
			gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR); 
		    gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR); 
		}else if (this.texture.textureType == Constants.PixelTexture){
			PixelTextureObject textureObject = (PixelTextureObject)this.texture;
			GL gl = GLAutoDrawable.getGL();
			textureObject.prepareTexture(gl);
			textureObject.bindTexture(gl);
			//gl.glBindTexture(GL.GL_TEXTURE_2D, textureObject.getTextureId());
			gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
			gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
			gl.glTexParameteri (GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
			gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR); 
		    gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR); 
		}
	}
	
	public String toString() {
		return "Properties";
	}
	
	public void setMaterial(MaterialObject material) {
		this.material = material;
	}
	
	public void setTexture(TextureObject texture) {
		this.texture = texture;
	}
	
	public void setTextureTransform(TextureTransformObject textureTransform) {
		this.textureTransform = textureTransform;
	}
	
	public boolean isTextureSeted(){
		if (this.texture == null)return false;
		else return true;
	}
	
}

